﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Input;
using Controls = Windows.UI.Xaml.Controls;
using Shapes = Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media;
using Windows.UI;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using BoolanSlide.ElementMenu;
using BoolanSlide.BooCommon;
using BoolanSlide.RedoUndo;
using Windows.UI.Xaml.Media.Imaging;
using Configuration;
using BoolanSlide.Language;

namespace BoolanElement
{
    public class BooArrow : BooLineBase, ILineStyleController, IFocusEllOperation
    {
        private Shapes.Path arrow;

        private LineMenu lineMenu;

        public override MenuBase UIMenu
        {
            get { return lineMenu; }
        }

        public Shapes.Path Arrow
        {
            get { return arrow; }
            set { arrow = value; }
        }

        public PathGeometry ArrowPathGeometry
        {
            get { return (PathGeometry)arrow.Data; }
            set { arrow.Data = value;
            }
        }

        public PathFigureCollection Figures
        {
            get { return ((PathGeometry)arrow.Data).Figures; }
            set { ((PathGeometry)arrow.Data).Figures = value; }
        }

        public PathFigure ArrowFigure
        {
            get { return ((PathGeometry)arrow.Data).Figures[0]; }
            set { ((PathGeometry)arrow.Data).Figures[0] = value; }
        }

        public PathSegmentCollection ArrowSegments
        {
            get { return ((PathGeometry)arrow.Data).Figures[0].Segments; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments = value; }
        }

        public LineSegment Line1
        {
            get { return (LineSegment)((PathGeometry)arrow.Data).Figures[0].Segments[0]; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments[0] = value; }
        }

        public LineSegment Line2
        {
            get { return (LineSegment)((PathGeometry)arrow.Data).Figures[0].Segments[1]; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments[1] = value; }
        }

        public LineSegment Line3
        {
            get { return (LineSegment)((PathGeometry)arrow.Data).Figures[0].Segments[2]; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments[2] = value; }
        }

        public LineSegment Line4
        {
            get { return (LineSegment)((PathGeometry)arrow.Data).Figures[0].Segments[3]; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments[3] = value; }
        }

        public LineSegment Line5
        {
            get { return (LineSegment)((PathGeometry)arrow.Data).Figures[0].Segments[4]; }
            set { ((PathGeometry)arrow.Data).Figures[0].Segments[4] = value; }
        }
        Shapes.Line FindLine;

        TranslateTransform topT;
        TranslateTransform bottomT;

        ControlPanel lineControlPanel;

        BooArrowElement arrowElement;
        public BooArrowElement ArrowElement
        {
            get
            {
                return arrowElement;
            }
        }

        public override BooElement Element
        {
            set { arrowElement = (BooArrowElement)value; }
            get { return arrowElement; }
        }
  
        public BooArrow(BooArrowElement element,SaveForRedoUndo saveForRedoUndo):base(element)
        {
            this.arrowElement = element;
            InitOriginal();
            Focus.InitFocusEvent(this);
            InitLineControlPanel();
            base.saveForRedoUndo = saveForRedoUndo;
            topT = new TranslateTransform();
            bottomT = new TranslateTransform();

            Focus.FocusElls.left_top_ell.RenderTransform = topT;
            Focus.FocusElls.right_bottom_ell.RenderTransform = bottomT;
            LostFocus();

            LanguageManager.LanguageChanged += LanguageManager_LanguageChanged;
        }

        void LanguageManager_LanguageChanged(object sender)
        {
            lineControlPanel.ModifyTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, 0);
        }

        public BooArrow(BooArrowElement element):base(element)
        {
            this.arrowElement = element;
            InitForThumbNails();
        }

        public void ShowLineControlPanel(IStyleController lineController)
        {
            if (lineControlPanel != null)
            {
                lineControlPanel.ShowControlPanel(lineController);
            }
        }

        public void HideLineControlPanel()
        {
            if (lineControlPanel != null)
            {
                lineControlPanel.HideControlPanel();
            }
        }

        public void InitLineControlPanel()
        {
            lineControlPanel = new ControlPanel();
            LineStyle lineStyle = new LineStyle();

            lineControlPanel.AddTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, lineStyle);
        }
        public void InitContextMenu()
        {
            lineMenu = new LineMenu(this);
        }

        private void InitOriginal()
        {
            CreateShape();
            InitializeActionMap(BooCanvas);
            InitContextMenu();
            Focus.InsertFocusEllipses(BooCanvas);
            Focus.FocusElls.left_top_ell.Margin = new Thickness(this.arrowElement.PointX.X - FocusEllipses.FocusTouchAreaLength / 2,
                this.arrowElement.PointX.Y - FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            Focus.FocusElls.right_bottom_ell.Margin = new Thickness(this.arrowElement.PointY.X - FocusEllipses.FocusTouchAreaLength / 2,
                this.arrowElement.PointY.Y - FocusEllipses.FocusTouchAreaLength / 2, 0, 0);

        }
        private void InitForThumbNails()
        {
            CreateShape();
            ApplyTransform(BooCanvas);
            BooCanvas.ManipulationMode = ManipulationModes.None;
        }

        public void CreateShape()
        {
            InitLine();
            InitFindLine();
            InitCanvas();

            BooCanvas.Children.Add(Arrow);
            BooCanvas.Children.Add(FindLine);
           
        }

        public void InitLine()
        {
            arrow = new Shapes.Path();
            arrow.Data=new PathGeometry();
            ((PathGeometry)arrow.Data).Figures=new PathFigureCollection();
            ((PathGeometry)arrow.Data).Figures.Add(new PathFigure());
            ((PathGeometry)arrow.Data).Figures[0].Segments=new PathSegmentCollection();
            ((PathGeometry)arrow.Data).Figures[0].Segments.Add(new LineSegment());
            ((PathGeometry)arrow.Data).Figures[0].Segments.Add(new LineSegment());
            ((PathGeometry)arrow.Data).Figures[0].Segments.Add(new LineSegment());
            ((PathGeometry)arrow.Data).Figures[0].Segments.Add(new LineSegment());
            ((PathGeometry)arrow.Data).Figures[0].Segments.Add(new LineSegment());

            ArrowFigure.StartPoint = new Point(this.arrowElement.Point1.X, this.arrowElement.Point1.Y);
            Line1.Point = new Point(this.arrowElement.Point2.X, this.arrowElement.Point2.Y);
            Line2.Point = new Point(this.arrowElement.Point3.X, this.arrowElement.Point3.Y);
            Line3.Point = new Point(this.arrowElement.Point4.X, this.arrowElement.Point4.Y);
            Line4.Point = new Point(this.arrowElement.Point5.X, this.arrowElement.Point5.Y);
            Line5.Point = new Point(this.arrowElement.Point6.X, this.arrowElement.Point6.Y);

            Arrow.Stroke = new SolidColorBrush(arrowElement.LineColor);
            Arrow.Fill = new SolidColorBrush(this.arrowElement.LineColor);
            Arrow.StrokeThickness = this.arrowElement.BorderWidth;
        }

        public void InitFindLine()
        {
            FindLine = new Shapes.Line();
            FindLine.X1 = arrowElement.PointX.X;
            FindLine.Y1 = arrowElement.PointX.Y;
            FindLine.X2 = arrowElement.PointY.X;
            FindLine.Y2 = arrowElement.PointY.Y;
            FindLine.Stroke = new SolidColorBrush(Colors.Transparent);
            FindLine.StrokeThickness = 40;

            FindLine.PointerPressed += FindLine_PointerPressed;
            FindLine.PointerReleased += FindLine_PointerReleased;
        }

        void FindLine_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            if (System.DateTime.Now.Ticks - PressedTicks < GlobalVariable.ShowMenuTime && Manipulationed == false)
                this.lineMenu.ShowMenu();
            Manipulationed = false;
        }

        void FindLine_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            PressedTicks = System.DateTime.Now.Ticks;
            Manipulationed = false;
        }

        
        public void InitCanvas()
        {
            BooCanvas = new Controls.Canvas();
        }


        public override void LostFocus()
        {           
            base.LostFocus();
            HideLineControlPanel();
            lineMenu.HideMenu();
        }

        public override void GotFocus()
        {
            base.GotFocus();     
            ShowLineControlPanel(this);
            this.Focus.FocusElls.left_middle_ell.Visibility = Visibility.Collapsed;
            this.Focus.FocusElls.right_middle_ell.Visibility = Visibility.Collapsed;
            this.Focus.FocusElls.middle_bottom_ell.Visibility = Visibility.Collapsed;
            this.Focus.FocusElls.left_bottom_ell.Visibility = Visibility.Collapsed;
            this.Focus.FocusElls.middle_top_ell.Visibility = Visibility.Collapsed;
            this.Focus.FocusElls.right_top_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.rotate_ell.Visibility = Visibility.Collapsed;
        }
   
        public void ChangeBorderColor(Color color)
        {
            this.ArrowElement.LineColor = color;
            arrowElement.PropertyChange("Style");
            RedoUndoHelper.SaveStatus(this);
        }

        public Color GetBorderColor()
        {
            return this.ArrowElement.LineColor;
        }

        public void ChangeBorderWidth(double width, bool isSave = false)
        {
            this.ArrowElement.BorderWidth = width;
            arrowElement.PropertyChange("Style");
            if (isSave)
                RedoUndoHelper.SaveStatus(this);
        }

        public double GetBorderWidth()
        {
            return this.ArrowElement.BorderWidth;
        }

        public void left_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;

            arrowElement.Point1 = new Point(arrowElement.Point1.X + width, arrowElement.Point1.Y + height);
            ArrowFigure.StartPoint = arrowElement.Point1;

            double lineLength = BooMath.Length(arrowElement.Point1, arrowElement.Point4);
            lineLength -= 10;
            Point pt2 = BooMath.MovePoint(arrowElement.Point4, arrowElement.Point1, lineLength);
            arrowElement.Point2 = pt2;
            arrowElement.Point6 = pt2;

            Point pt3 = BooMath.RotatePoint(arrowElement.Point1, arrowElement.Point4, 20 * Math.PI / 180);
            pt3 = BooMath.MovePoint(pt3, arrowElement.Point4, 8.944);
            arrowElement.Point3 = pt3;

            Point pt5 = BooMath.RotatePoint(arrowElement.Point1, arrowElement.Point4, -20 * Math.PI / 180);
            pt5 = BooMath.MovePoint(pt5, arrowElement.Point4, 8.944);
            arrowElement.Point5 = pt5;

            this.arrowElement.PointX = new Point(arrowElement.Point1.X, arrowElement.Point1.Y);

            arrowElement.PropertyChange("Shape");
            e.Handled = true;
        }

        public void middle_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;
            Point orig = arrowElement.Point4;

            arrowElement.Point4= new Point(arrowElement.Point4.X+width,arrowElement.Point4.Y+height);

            double lineLength = BooMath.Length(arrowElement.Point1, arrowElement.Point4);
            lineLength -= 10;
            Point pt2 = BooMath.MovePoint(arrowElement.Point4, arrowElement.Point1, lineLength);
            arrowElement.Point2 = pt2;
            arrowElement.Point6 = pt2;

            Point pt3 = BooMath.RotatePoint(arrowElement.Point1, arrowElement.Point4, 20*Math.PI/180);
            pt3 = BooMath.MovePoint(pt3, arrowElement.Point4, 8.944);
            arrowElement.Point3 = pt3;

            Point pt5 = BooMath.RotatePoint(arrowElement.Point1, arrowElement.Point4, -20 * Math.PI / 180);
            pt5 = BooMath.MovePoint(pt5, arrowElement.Point4, 8.944);
            arrowElement.Point5 = pt5;

            this.arrowElement.PointY = new Point(arrowElement.Point4.X, arrowElement.Point4.Y);

            arrowElement.PropertyChange("Shape");
            e.Handled = true;
        }

        public override void LoadFromElement(BooElement booElement)
        {
            base.LoadFromElement(booElement);
            base.ApplyTransform(BooCanvas);
            ApplyShapeChange();
            ApplyStyleChange();
        }

        public override void ApplyShapeChange()
        {
            ArrowFigure.StartPoint = arrowElement.Point1;
            Line1.Point = new Point(this.arrowElement.Point2.X, this.arrowElement.Point2.Y);
            Line2.Point = new Point(this.arrowElement.Point3.X, this.arrowElement.Point3.Y);
            Line3.Point = new Point(this.arrowElement.Point4.X, this.arrowElement.Point4.Y);
            Line4.Point = new Point(this.arrowElement.Point5.X, this.arrowElement.Point5.Y);
            Line5.Point = new Point(this.arrowElement.Point6.X, this.arrowElement.Point6.Y);
            FindLine.X1 = arrowElement.PointX.X;
            FindLine.Y1 = arrowElement.PointX.Y;
            FindLine.X2 = arrowElement.PointY.X;
            FindLine.Y2 = arrowElement.PointY.Y;
            if (topT != null)
            {
                topT.X = arrowElement.PointX.X;
                topT.Y = arrowElement.PointX.Y;
            }
            if (bottomT != null)
            {
                bottomT.X = arrowElement.PointY.X;
                bottomT.Y = arrowElement.PointY.Y;
            }
            Focus.FocusElls.left_top_ell.Margin = new Thickness(-FocusEllipses.FocusTouchAreaLength / 2, -FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            Focus.FocusElls.right_bottom_ell.Margin = new Thickness(-FocusEllipses.FocusTouchAreaLength / 2, -FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
        } 

        public void middle_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void middle_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void middle_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public override BooLineBaseElement BooLineBaseElement
        {
            get { throw new NotImplementedException(); }
        }

        public override Point GetMenuDisplayPosition()
        {
            Point ret = new Point();
            double yLoc = 0;
            if (arrowElement.PointX.Y < arrowElement.PointY.Y)
            {
                yLoc = arrowElement.PointX.Y;
            }
            else
            {
                yLoc = arrowElement.PointY.Y;
            }
            yLoc += arrowElement.ElementTransform.Translate.Y;

            double xLoc = (arrowElement.PointX.X + arrowElement.PointY.X) / 2 + arrowElement.ElementTransform.Translate.X;
            return new Point(xLoc, yLoc);
        }

        public override void ApplyStyleChange()
        {
            Arrow.Fill = new SolidColorBrush(arrowElement.LineColor);
            Arrow.Stroke = new SolidColorBrush(arrowElement.LineColor);
            Arrow.StrokeThickness = arrowElement.BorderWidth;
        }


        public int GetZIndex()
        {
            return this.ArrowElement.ElementTransform.ZIndex;
        }

        public void ChangeZIndexTo(int index)
        {
            this.ArrowElement.ElementTransform.ZIndex = index;
        }

        public void rotate_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void rotate_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }


        public void rotate_ell_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }
    }
}
